package com.comall.dc.banktest.domain.model;

import com.comall.dc.banktest.domain.exception.AccountNoAuthException;
import com.comall.dc.banktest.domain.exception.BalanceInsufficientException;
import com.comall.dc.banktest.infrastructure.core.AccountStatusEnum;
import com.comall.dc.banktest.infrastructure.core.Constant;
import com.comall.dc.banktest.infrastructure.entity.AccountPO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.util.DigestUtils;

import java.io.Serializable;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.UUID;

@Getter
@NoArgsConstructor
public class Account implements Serializable {


    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "ID")
    private Integer id;

    @ApiModelProperty(value = "用户身份证")
    private String idCard;

    @ApiModelProperty(value = "账户密码")
    private String accountPassword;

    @ApiModelProperty(value = "用户姓名")
    private String userName;

    @ApiModelProperty(value = "用户电话")
    private String userPhone;

    @ApiModelProperty(value = "用户地址")
    private String userAddress;

    @ApiModelProperty(value = "用户工作")
    private String userJob;

    @ApiModelProperty(value = "加密盐")
    private String accountSalt;

    @ApiModelProperty(value = "账户状态(0:未激活, 1:正常, 2:冻结)")
    private AccountStatusEnum accountStatus;

    @ApiModelProperty(value = "账户余额")
    private BigDecimal balance;

    @ApiModelProperty(value = "创建时间, 开户时间")
    private LocalDateTime createTime;

    public Account(String idCard, String userName, String userPhone, String userAddress, String userJob){

        this.idCard = idCard;
        this.userName = userName;
        this.userPhone = userPhone;
        this.userAddress = userAddress;
        this.userJob = userJob;
        this.accountSalt = UUID.randomUUID().toString().replace("-", "");
        this.accountPassword = DigestUtils.md5DigestAsHex((
                this.accountSalt + Constant.ORIGINAL_PASSWORD).getBytes(StandardCharsets.UTF_8));
        this.accountStatus = AccountStatusEnum.NOT_ACTIVE;
        this.balance = new BigDecimal("0");


    }

    public Account(AccountPO accountPO){
        this.id = accountPO.getId();
        this.idCard = accountPO.getIdCard();
        this.userName = accountPO.getUserName();
        this.userPhone = accountPO.getUserPhone();
        this.userAddress = accountPO.getUserAddress();
        this.userJob = accountPO.getUserJob();
        this.accountSalt = accountPO.getAccountSalt();
        this.accountPassword = accountPO.getAccountPassword();
        this.accountStatus = AccountStatusEnum.of(accountPO.getAccountStatus());
        this.balance = accountPO.getBalance();
        this.createTime = accountPO.getCreateTime();
    }

    public void activate(String accountPassword) throws AccountNoAuthException{
        if (!this.accountStatus.equals(AccountStatusEnum.NOT_ACTIVE)){
            throw new AccountNoAuthException();
        }
        this.accountPassword = DigestUtils.md5DigestAsHex((
                this.accountSalt + accountPassword).getBytes(StandardCharsets.UTF_8));
        this.accountStatus = AccountStatusEnum.NORMAL;
    }

    public void freeze(){
        this.accountStatus = AccountStatusEnum.FROZEN;
    }

    public void addBalance(BigDecimal value){
        BigDecimal newValue = this.balance.add(value);
        this.balance = newValue;

    }

    public void subtractBalance(BigDecimal value) throws BalanceInsufficientException{
        BigDecimal newValue = this.balance.subtract(value);
        if (newValue.compareTo(BigDecimal.ZERO) >= 0){
            this.balance = newValue;
        }
        else {
            throw new BalanceInsufficientException();
        }
    }


    /**
     * 是否密码正确
     * @param password 密码
     * @return 是否密码正确
     */
    public boolean isAuthPass(String password){
        return password != null && DigestUtils
                .md5DigestAsHex((this.getAccountSalt() + password).getBytes(StandardCharsets.UTF_8))
                .equals(this.getAccountPassword());

    }

    /**
     * 是否已冻结
     * @return 是否已冻结
     */
    public boolean isFrozen(){
        return AccountStatusEnum.FROZEN.equals(this.getAccountStatus());
    }
}
